<?php

namespace common\helpers;

use Yii;
use common\logics\SiteMapLogic;

/**
 * 格式化地址处理器
 *
 * @author emhome <emhome@163.com>
 * @since 2.0
 */
class Url extends \yii\helpers\BaseUrl {

    //
    const CHANNEL_LOCAL = 0;
    const CHANNEL_FTP = 1;
    const CHANNEL_OSS = 2;
    const CHANNEL_DEFAULT = self::CHANNEL_OSS;

    /**
     * 获取H5页面地址
     * @param string $channel
     * @return string
     */
    public static function channelHosts() {
        return [
            static::CHANNEL_LOCAL => Yii::getAlias('@attachUrl'),
            static::CHANNEL_FTP => Yii::getAlias('@attachUrl'),
            static::CHANNEL_OSS => Yii::getAlias('@attachUrl'),
        ];
    }

    /**
     * 获取H5页面地址
     * @param string $channel
     * @return string
     */
    public static function channelHost($channel = null) {
        $hosts = static::channelHosts();
        if ($channel === null) {
            $channel = static::CHANNEL_DEFAULT;
        }
        if (is_numeric($channel)) {
            return ArrayHelper::getValue($hosts, $channel, Yii::getAlias('@attachUrl'));
        }
        foreach ($hosts as $host) {
            if (strpos($host, $channel) !== false) {
                return $host;
            }
        }
        return $channel;
    }

    /**
     * 获取H5页面地址
     * @param string $channel
     * @return string
     */
    public static function channelId($channel = null) {
        $hosts = static::channelHosts();
        if ($channel === null) {
            $channel = Yii::getAlias('@attachUrl');
        }
        foreach ($hosts as $id => $host) {
            if (strpos($host, $channel) !== false) {
                return $id;
            }
        }
        return static::CHANNEL_DEFAULT;
    }

    /**
     * 获取H5页面地址
     * @param string $url
     * @return string
     */
    public static function getChannelByPath($url) {
        $hosts = static::channelHosts();
        foreach ($hosts as $channel => $host) {
            if (strpos($url, $host) === 0) {
                return $channel;
            }
        }
        return static::CHANNEL_DEFAULT;
    }

    /**
     * 获取H5页面地址
     * @param string $url
     * @return string
     */
    public static function relativePath($url, $replace = null) {
        if (!$replace) {
            $replace = static::channelHost();
        }
        $path = str_replace($replace, '', $url);
        if (static::isRelative($path)) {
            $path = ltrim($path, '/');
            return $path ? '/' . $path : '';
        }
        return $path;
    }

    /**
     * 获取H5页面地址
     * @param string $uri
     * @return string
     */
    public static function h5($uri) {
        $domain = ArrayHelper::getValue(Yii::$app->params, 'domain.h5');
        return static::toRemote(static::to($uri), $domain);
    }

    /**
     * 获取H5页面地址
     * @param string $uri
     * @return string
     */
    public static function routelink($uri, $params = [], $type = 'path') {
        $url = static::to($uri);
        $route = [
            $type => $type === 'path' ? $url : ltrim($url, '/'),
        ];
        if (!empty($params)) {
            $format = 'query';
            if ($type === 'name') {
                $format = 'params';
            }
            $route[$format] = $params;
        }
        return $route;
    }

    /**
     * 获取H5页面地址
     * @param string $uri
     * @return string
     */
    public static function weblink($alias, $data = []) {
        return SiteMapLogic::findByData($alias, $data);
    }

    /**
     * 阿里直播流地址格式
     * @param string $uri
     * @param string $key
     * @param string $timestamp
     * @param string $rand
     * @return string
     */
    public static function aliyunLiveStream($uri, $key, $timestamp, $rand = 0) {
        $livePython = Yii::getAlias('@common/data/python/live.py');
        $data = [];
        exec("python3 $livePython $uri $key $timestamp", $data);
        return array_pop($data);
    }

    /**
     * 获取分享地址
     * @param string $uri
     * @return string
     */
    public static function share($type, $params = [], $encrypt = false) {
        $domain = ArrayHelper::getValue(Yii::$app->params, 'domain.share');
        $uri = ['/share', 't' => $type];
        if (!empty($params)) {
            if ($encrypt) {
                $string = http_build_query($params);
                if ($string) {
                    $str = Yii::$app->security->encryptByKey($string, '123');
                    $uri['d'] = static::safeEncode($str);
                }
            } else {
                $uri = ArrayHelper::merge($uri, $params);
            }
        }
        return static::toRemote(static::to($uri), $domain);
    }

    /**
     * 获取视频地址
     * @param string $original
     * @param string|null $host
     * @return string
     */
    public static function video($original, $host = null) {
        return static::toRemote($original, $host ? $host : Yii::getAlias('@attachUrl'));
    }

    /**
     * 获取远程附件地址
     * @param string $original
     * @param string|null $host
     * @return string
     */
    public static function attach($original, $host = null) {
        $channelHost = static::channelHost($host);
        return static::toRemote($original, $channelHost);
    }

    /**
     * 获取远程附件地址
     * @param string $original
     * @param string|null $host
     * @return string
     */
    public static function attachAvatar($original, $host = null) {
        return static::attach($original, $host ? $host : Yii::getAlias('@attachUrl'));
    }

    /**
     * 格式化内容成可访问的Url地址
     * @param string $url
     * @param string|null $host
     * @return string
     */
    public static function removeAttachAlias($url, $host = null) {
        if (!$url) {
            return '';
        }
        if (!static::isRelative($url)) {
            $host = $host ?: Yii::getAlias('@attachUrl');
            if ($host && !static::isRelative($host)) {
                $url = '/' . ltrim(str_replace($host, '', $url), '/');
            }
        }
        return $url;
    }

    /**
     * 格式化内容成可访问的Url地址
     * @param string $original
     * @param string|null $host
     * @return string
     */
    public static function toRemote($original, $host = null) {
        if (!$original) {
            return '';
        }
        if (!static::isRelative($original)) {
            return $original;
        }
        if ($host && !static::isRelative($host)) {
            return rtrim($host, '/') . '/' . ltrim($original, '/');
        }
        return $original;
    }

    /**
     * 生成短网址
     * @param string $url
     * @return string
     */
    public static function toShort($url) {
        if (is_array($url)) {
            $url = static::to($url);
        }
        $result = sprintf("%u", crc32($url));
        $sUrl = '';
        while ($result > 0) {
            $s = $result % 62;
            if ($s > 35) {
                $s = chr($s + 61);
            } elseif ($s > 9 && $s <= 35) {
                $s = chr($s + 55);
            }
            $sUrl .= $s;
            $result = floor($result / 62);
        }
        return $sUrl;
    }

    /**
     * 生成短网址
     * @param string $url
     * @return string
     */
    public static function shorturl($url) {
        $input = static::to($url);
        $base32 = [
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
            'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
            'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
            'y', 'z', '0', '1', '2', '3', '4', '5'
        ];
        $hex = md5($input);
        $hexLen = strlen($hex);
        $subHexLen = $hexLen / 8;
        $output = array();
        for ($i = 0; $i < $subHexLen; $i++) {
            //把加密字符按照8位一组16进制与0x3FFFFFFF(30位1)进行位与运算
            $subHex = substr($hex, $i * 8, 8);
            $int = 0x3FFFFFFF & (1 * filter_var("0x" . $subHex, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX));
            $out = '';
            for ($j = 0; $j < 6; $j++) {
                //把得到的值与0x0000001F进行位与运算，取得字符数组chars索引
                $val = 0x0000001F & $int;
                $out .= $base32[$val];
                $int = $int >> 5;
            }
            $output[] = $out;
        }

        return $output;
    }

    /**
     * url base64编码
     * @param string $string
     * @return string
     */
    public static function safeEncode($string) {
        $data = base64_encode($string);
        return str_replace(array('+', '/', '='), array('-', '_', ''), $data);
    }

    /**
     * url base64解码
     * @param string $string
     * @return string
     */
    public static function safeDecode($string) {
        $data = str_replace(array('-', '_'), array('+', '/'), $string);
        $mod4 = strlen($data) % 4;
        if ($mod4) {
            $data .= substr('====', $mod4);
        }
        return base64_decode($data);
    }

}
